﻿param (
    [string]$Subject,
    [string]$Duration,
    [string]$ExePath,
    [string]$Password
)

# ------------------------- 清理路径中的隐藏字符 -------------------------
$ExePath = $ExePath.Trim([char]0x202A)  # 移除 Unicode 左到右标记

# ------------------------- 验证文件是否存在 -------------------------
if (-not (Test-Path $ExePath)) {
    Write-Host "错误：文件 '$ExePath' 不存在"
    exit 1
}

# ------------------------- 解析有效期 -------------------------
$validUntilDate = Get-Date
if ($Duration -match '^(\d+)([ymdhHnN])$') {
    $value = [int]$matches[1]
    $unit = $matches[2].ToLower()  # 统一转为小写
    
    switch ($unit) {
        'y' { $validUntilDate = $validUntilDate.AddYears($value) }
        'm' { $validUntilDate = $validUntilDate.AddMonths($value) }
        'd' { $validUntilDate = $validUntilDate.AddDays($value) }
        'h' { $validUntilDate = $validUntilDate.AddHours($value) }
        'n' { $validUntilDate = $validUntilDate.AddMinutes($value) }
        default { 
            Write-Host "无效的单位"
            exit 1
        }
    }
} else {
    Write-Host "无效的有效期格式"
    exit 1
}

# ------------------------- 创建自签名证书 -------------------------
try {
    $cert = New-SelfSignedCertificate `
        -Type CodeSigningCert `
        -Subject "CN=$Subject" `
        -KeyExportPolicy Exportable `
        -CertStoreLocation "Cert:\CurrentUser\My" `
        -KeySpec Signature `
        -NotAfter $validUntilDate -ErrorAction Stop
} catch {
    Write-Host "创建证书失败: $_"
    exit 1
}

# ------------------------- 导出 PFX 证书 -------------------------
$pfxPath = "$env:TEMP\temp_signing_cert.pfx"
try {
    Export-PfxCertificate -Cert $cert -FilePath $pfxPath `
        -Password (ConvertTo-SecureString -String $Password -Force -AsPlainText) -ErrorAction Stop
} catch {
    Write-Host "导出 PFX 证书失败: $_"
    exit 1
}

# ------------------------- 使用 signtool 签名 -------------------------
$signtool = "C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe"
if (-not (Test-Path $signtool)) {
    Write-Host "错误: 未找到 signtool.exe"
    exit 1
}

try {
    & $signtool sign /f $pfxPath /p $Password /tr http://timestamp.digicert.com /td sha256 /fd sha256 "$ExePath"
    if ($LASTEXITCODE -ne 0) {
        throw "签名失败 (错误码: $LASTEXITCODE)"
    }
    Write-Host "成功签名: $ExePath"
} catch {
    Write-Host "签名过程中出错: $_"
    exit 1
}

# ------------------------- 导出 PEM 证书 -------------------------
$exeDir = [System.IO.Path]::GetDirectoryName($ExePath)
$certOutPath = Join-Path $exeDir "sign-cert.pem"

try {
    # 导出 PEM 格式的证书
    $certBytes = $cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)
    $base64Cert = [System.Convert]::ToBase64String($certBytes, [System.Base64FormattingOptions]::InsertLineBreaks)
    $pemContent = "-----BEGIN CERTIFICATE-----`n$base64Cert`n-----END CERTIFICATE-----"
    [System.IO.File]::WriteAllText($certOutPath, $pemContent)
    Write-Host "证书已导出到: $certOutPath"
} catch {
    Write-Host "导出 PEM 证书失败: $_"
    exit 1
}

# ------------------------- 清理临时文件 -------------------------
try {
    Remove-Item -Path "Cert:\CurrentUser\My\$($cert.Thumbprint)" -Force -ErrorAction SilentlyContinue
    Remove-Item $pfxPath -Force -ErrorAction SilentlyContinue
} catch {
    Write-Host "清理临时文件时出错: $_"
}

exit 0